home *** CD-ROM | disk | FTP | other *** search
- /*_________________________________________________________________________________
-
- File: XTIShell.c
-
- This file contains the C routines called by XTIShell.a for the implementation
- of the AURP atlk calls. It is based on the X25Tunnel atlk code and some X25
- specific things have been left in to provide an example. Hints on things that
- may need to be changed are provided throughout.
-
- It is assumed that the implementation of XTI that the code was written to
- (MacOSI) is standard enough that XTI specific changes will not need to be made.
- This assumption has not yet been put to the test. If you are not using MacOSI
- or TII, be careful!
-
- Apple Computer, Inc.
- Copyright (C) 1992,1993. All rights reserved.
-
- Revision History:
-
- __________________________________________________________________________________*/
-
- #include <GestaltEqu.h>
- #include <ToolUtils.h>
- #include <String.h>
- #include <Memory.h>
- #include "AURPInterface.h"
- #include "XTIShell.h"
- #include "XTIShell_r.h"
-
- /* ___ XTI flag bits ___ */
- #define XTIInit 0 // bit 0, set if init'ed
- #define XTIClose 1 // bit 1, set if closing
- #define XTILapInst 2 // bit 2, set if LAP Write code is installed
-
- /* ___ Log string indexes for our array ___ */
- #define kDialLogIx kDialLog-1
- #define kAnswerLogIx kAnswerLog-1
- #define kConnectLogIx kConnectLog-1
- #define kConnClearLogIx kConnClearLog-1
- #define kConnDownLogIx kConnDownLog-1
- #define kConnReqFailLogIx kConnReqFailLog-1
- #define kPasswordLogIx kPasswordLog-1
-
- //
- // This timer is used for both opening a connection and reconnecting.
- // You may eventually want to separate these timers, or put it in a resource
- // for fine tuning by you or the user if necessary.
- //
- /* ___ retry timer ___ */
- #define kRetryTimer 10000 // retry every 10 seconds
-
- /* prototypes for the routines called from the assember code in XTIShell.a */
- OSErr DOXTIINSTALL(XTIShellVarsPtr myVarsPtr, XTIacfgPtr aConfigPtr, TADEVSigRecPtr aSigPtr);
- OSErr DOXTIDISCONNECT(XTIShellVarsPtr myVarsPtr);
- OSErr DOXTISHUTDOWN(XTIShellVarsPtr myVarsPtr);
- OSErr XTIWRITE(XTIShellVarsPtr myVarsPtr);
- OSErr XTICONNECT(XTIShellVarsPtr myVarsPtr);
-
- /* prototypes for the local routines */
- static void do_try_open(void);
- static void try_open(void);
- static int try_reconnect( XTIShellVarsPtr myVarsPtr );
- static int do_open( XTIShellVarsPtr myVarsPtr );
- static int do_bind( XTIShellVarsPtr myVarsPtr );
- static void do_connect( XTIShellVarsPtr myVarsPtr );
- static void reconnect(void);
- static void get_disconnect( XTIShellVarsPtr myVarsPtr );
- static void doSendErr ( XTIShellVarsPtr myVarsPtr );
- static void doReadErr ( XTIShellVarsPtr myVarsPtr );
- static void get_data( XTIShellVarsPtr myVarsPtr );
- static void get_connect( XTIShellVarsPtr myVarsPtr );
- static int get_listen( XTIShellVarsPtr myVarsPtr );
- static void asyncReceive (int fd, int event, unsigned long providerInfo,int errno, void *cookie);
- static void check_send( XTIShellVarsPtr myVarsPtr, int dataSent );
- static void Bin2Ascii(unsigned char *bin, unsigned char len, unsigned char *ascii);
- static XTIShellVarsPtr GETGLOBALS (void);
-
- /*______________________________________________________________________________
-
- DOXTIINSTALL - Do the install. Several modifications must be made in this
- routine.
-
- Returns: error code
-
- Parameters: --> myVarsPtr, aConfigPtr, aSigPtr
-
- ______________________________________________________________________________*/
-
- OSErr DOXTIINSTALL(XTIShellVarsPtr myVarsPtr,
- XTIacfgPtr aConfigPtr,
- TADEVSigRecPtr aSigPtr)
-
- {
- OSErr result;
- Ptr memBlockPtr;
- char i;
- CShellGlobalsPtr myGlobals;
- long ProcessorType;
- ReOpenTMRecPtr myReOpenTMRecPtr;
- dtRecPtr mydtRecPtr;
-
-
- /* set up memcpy */
- ProcessorType = gestalt68000;
- result = Gestalt(gestaltProcessorType, &ProcessorType);
- if (ProcessorType != gestalt68000)
- memcpySetLongMove (ProcessorType);
-
- /* Get memory globals */
- myVarsPtr->cGlobals = (CShellGlobalsPtr) GETSYSMEM(sizeof(CShellGlobals));
- if (!myVarsPtr->cGlobals)
- return(-1);
- myGlobals = myVarsPtr->cGlobals;
-
- /* Get memory for log messages */
- memBlockPtr = GETSYSMEM(kNumLogStr*kMaxLogStrLen);
- if (!memBlockPtr)
- return(-1);
-
- /* Get memory for time manager record */
- myGlobals->openTMRec = (ReOpenTMRecPtr) GETSYSMEM (sizeof(ReOpenTMRec));
- if (!myGlobals->openTMRec)
- return(-1);
-
- /* Get memory for deferred task manager record */
- myGlobals->mydtRec = (dtRecPtr) GETSYSMEM (sizeof(dtRec));
- if (!myGlobals->mydtRec)
- return(-1);
-
- /* initialize log string Ptrs */
- for (i=0; i<kNumLogStr; i++) {
- myGlobals->logStr[i] = memBlockPtr;
- memBlockPtr += kMaxLogStrLen;
- }
-
- /* Get the log strings */
- for (i=0; i< kNumLogStr; i++) {
- GetIndString( (Str255) myGlobals->logStr[i], kXTILogStrID, i+1 );
- }
-
- /* save config record */
- myGlobals->theConfig = *aConfigPtr;
-
- /* initialize variables */
- myGlobals->fd = -1;
- myVarsPtr->otherNode = kNextIR;
- //
- // Fill in the appropriate line speed here. If you don't know it until
- // the connection has been established, fill in your best guess and
- // put the correct information in later.
- //
- myVarsPtr->lineSpeed = 9600;
- myVarsPtr->OurSlotId = aSigPtr->slot;
- myGlobals->bindComplete = false;
- myGlobals->isConnected = false;
- myGlobals->isReconnecting = false;
- myGlobals->toldConnDone = false;
- myGlobals->isFlowControlled = false;
- myGlobals->isSending = false;
- myGlobals->waitMoreData = false;
- myVarsPtr->rcvBufAvail = true;
- myVarsPtr->rcvPktsWaiting = 0;
- myGlobals->waitForBind = false;
-
- //
- // Fill in the maximum buffer size your link will allow here.
- //
- myVarsPtr->maxRPktSz = 618;
- //
- // The addressing scheme shown here is that of X.25. This needs to be
- // changed to support the addressing scheme of the link you are using.
- //
- myVarsPtr->remoteAddr[0] =
- myGlobals->theConfig.remoteAddr.ssaf.DTEaddr.X121Addr.len;
- Bin2Ascii(myGlobals->theConfig.remoteAddr.ssaf.DTEaddr.X121Addr.addr,
- myVarsPtr->remoteAddr[0],
- &myVarsPtr->remoteAddr[1]);
-
- /* Get memory for receive and send buffers */
- myGlobals->sendBuffer = GETSYSMEM( myVarsPtr->maxRPktSz );
- if (!myGlobals->sendBuffer) return(-1);
- myGlobals->receiveBuffer = GETSYSMEM( myVarsPtr->maxRPktSz );
- if (!myGlobals->receiveBuffer) return(-1);
-
- /* set up time manager variables for reconnect */
- myGlobals->tmInfo.tmAddr = (TimerProcPtr) reconnect;
- myGlobals->tmInfo.tmWakeUp = 0;
- myGlobals->tmInfo.tmReserved = 0;
- myGlobals->myA5 = GETMYA5();
-
- /* initialize deferred task manager record */
- mydtRecPtr = myGlobals->mydtRec;
- mydtRecPtr->qLink = 0;
- mydtRecPtr->qType = dtQType;
- mydtRecPtr->dtFlags = 0;
- mydtRecPtr->dtAddr = (ProcPtr) try_open;
- mydtRecPtr->dtParm = 0;
- mydtRecPtr->dtReserved = 0;
-
- /* set up time manager variables for open */
- myReOpenTMRecPtr = myGlobals->openTMRec;
- myReOpenTMRecPtr->tmInfo.tmAddr = (TimerProcPtr) do_try_open;
- myReOpenTMRecPtr->tmInfo.tmWakeUp = 0;
- myReOpenTMRecPtr->tmInfo.tmReserved = 0;
-
- /* install time manager task */
- if (myGlobals->theConfig.autoReconn) {
- InsTime((QElemPtr) myGlobals);
- }
- InsTime((QElemPtr) myGlobals->openTMRec);
-
- return(0);
- }
-
-
- /*______________________________________________________________________________
- DOXTIDISCONNECT(XTIShellVarsPtr myVarsPtr)
-
- Do the disconnect. This code should not need any modifications.
-
- Returns: error code
-
- Parameters: --> myVarsPtr
- ______________________________________________________________________________*/
-
- OSErr DOXTIDISCONNECT(XTIShellVarsPtr myVarsPtr)
-
- {
- CShellGlobalsPtr myGlobals = myVarsPtr->cGlobals;
-
- myGlobals->isConnected = false;
- myGlobals->isReconnecting = false;
- myGlobals->toldConnDone = false;
-
- /* cancel outstanding writes */
- if(myGlobals->isSending) {
- myGlobals->isSending = false;
- (*myVarsPtr->AURPDispatch)(kAURPWriteDone, myVarsPtr->AURPRefNum, myVarsPtr->wDSPtr, -1);
- }
-
- /* close the connection, don't care about unbind */
- if (myGlobals->fd != -1) {
- t_close (myGlobals->fd);
- myGlobals->fd = -1;
- }
-
- return (0);
- }
-
- /*______________________________________________________________________________
- DOXTISHUTDOWN - Do the shutdown. This code should not need any modifications
- unless additional memeory was allocated at AInstall time.
-
- Returns: error code
-
- Parameters: --> myVarsPtr
-
- Note: Only call link tool if port info var is non-zero.
- ______________________________________________________________________________*/
-
- OSErr DOXTISHUTDOWN(XTIShellVarsPtr myVarsPtr)
-
- {
- CShellGlobalsPtr myGlobals = myVarsPtr->cGlobals;
-
-
- /* Dispose the memory allocated in Install */
- if (myVarsPtr->cGlobals) {
-
- if (myGlobals->theConfig.autoReconn && myGlobals->tmInfo.tmAddr) {
- RmvTime((QElemPtr) myGlobals);
- }
- if(myGlobals->openTMRec->tmInfo.tmAddr)
- RmvTime((QElemPtr) myGlobals->openTMRec);
-
- if (myGlobals->sendBuffer)
- DisposPtr(myGlobals->sendBuffer);
- if (myGlobals->receiveBuffer)
- DisposPtr(myGlobals->receiveBuffer);
- if (myGlobals->logStr[0])
- DisposPtr(myGlobals->logStr[0]);
- if (myGlobals->openTMRec)
- DisposPtr((Ptr)myGlobals->openTMRec);
-
- DisposPtr((Ptr)myVarsPtr->cGlobals);
- myVarsPtr->cGlobals = 0;
- }
-
- return(noErr);
- }
-
- /*____________________________________________________________________________
- XTIWRITE (XTIShellVarsPtr myVarsPtr)
-
- Take a WDS element and write it out with t_snd. This code should not need
- any modification.
-
- Returns: error code
-
- Parameters: --> myVarsPtr
- ______________________________________________________________________________*/
-
- OSErr XTIWRITE(XTIShellVarsPtr myVarsPtr)
- {
- OSErr error;
- int event;
- Ptr tempBuffer;
- short i;
- CShellGlobalsPtr myGlobals = myVarsPtr->cGlobals;
-
- //
- // If we are connected and not sending and the WDS element sent is not empty,
- // write out the packect.
- //
- if(myGlobals->isConnected
- && !myGlobals->isSending
- && myVarsPtr->wDSPtr[0].entryLength != 0) {
-
- /* copy wds element to send buffer */
- myGlobals->sendBuffLen = 0;
- tempBuffer = myGlobals->sendBuffer;
- for(i = 0; myVarsPtr->wDSPtr[i].entryLength; i++) {
- if (myGlobals->sendBuffLen+myVarsPtr->wDSPtr[i].entryLength > myVarsPtr->maxRPktSz) {
- return(-1);
- }
- memcpy (tempBuffer, myVarsPtr->wDSPtr[i].entryPtr, myVarsPtr->wDSPtr[i].entryLength);
- myGlobals->sendBuffLen += myVarsPtr->wDSPtr[i].entryLength;
- tempBuffer += myVarsPtr->wDSPtr[i].entryLength;
- }
-
- /* now send the data */
- myGlobals->isSending = true;
- myGlobals->dataToSendPtr = myGlobals->sendBuffer;
- error = t_snd( myGlobals->fd, myGlobals->dataToSendPtr, myGlobals->sendBuffLen, 0 );
- if (error) {
- /* check error */
- switch (t_ERRNO( myGlobals->fd ))
- {
- case TFLOW:
- myGlobals->isFlowControlled = true;
- break;
-
- case TLOOK:
- event = t_look ( myGlobals->fd ) ;
- if (event == T_DISCONNECT)
- {
- get_disconnect( myVarsPtr );
- }
- else doSendErr( myVarsPtr );
- break;
-
- default:
- doSendErr( myVarsPtr );
- break;
-
- }
- }
-
- }
- else{
- return( -1 );
- }
-
- return( noErr );
-
- }
-
-
-
-
- /*____________________________________________________________________________
- XTICONNECT (XTIShellVarsPtr myVarsPtr)
-
- This routine logs that we are trying to connect and sets up a time manager
- task that will actually do the open. This code should not need any
- modifications.
-
- Returns: error code
-
- Parameters: --> myVarsPtr
- ______________________________________________________________________________*/
-
- OSErr XTICONNECT(XTIShellVarsPtr myVarsPtr)
- {
- CShellGlobalsPtr myGlobals = myVarsPtr->cGlobals;
-
-
- /* Log that we're initiating the connection */
- if (myGlobals->theConfig.isCalling)
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kDialLogIx]);
- else
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kAnswerLogIx]);
-
- PrimeTime((QElemPtr) myGlobals->openTMRec, kRetryTimer);
-
- return( 0 );
- }
-
- /*____________________________________________________________________________
- do_try_open (void)
-
- This routine is called by the Time Manager (installed at connect time). It
- sets up a deferred task to try the t_open. This code should not need any
- modifications.
-
- ______________________________________________________________________________*/
- static void
- do_try_open (void)
- {
- OSErr error;
- XTIShellVarsPtr myVarsPtr = GETGLOBALS();
- CShellGlobalsPtr myGlobals = myVarsPtr->cGlobals;
- long oldA5;
-
- oldA5 = GETMYA5();
- SETMYA5(myGlobals->myA5);
-
- if ((error = DTInstall ((QElemPtr) myGlobals->mydtRec)) != noErr)
- DebugStr ("\p Deferred Task Manager Returned Error");
-
- SETMYA5(oldA5);
-
- }
-
- /*____________________________________________________________________________
- try_open (XTIShellVarsPtr myVarsPtr)
-
- This is the deferred task which does all the work for the connect sequence
- (open, bind, connect). Currently, it will continue to install itself (via
- the Time Manager routine) forever. A suggestion for modification would be
- to set up a retry counter and limit the number of retries.
-
- ______________________________________________________________________________*/
- static void
- try_open(void)
- {
- XTIShellVarsPtr myVarsPtr = GETGLOBALS();
- CShellGlobalsPtr myGlobals = myVarsPtr->cGlobals;
- long oldA5;
-
- oldA5 = GETMYA5();
- SETMYA5(myGlobals->myA5);
-
-
- //
- // If waitForBind is true, we have already successfully opened an endpoint
- // and are waiting for a T_BINDCOMPLETE event. Just check the bindComplete
- // flag. If it is true, we are done, otherwise, set up the time manager to
- // call us again.
- //
- if(myGlobals->waitForBind) {
- if(!myGlobals->bindComplete) {
- PrimeTime((QElemPtr) myGlobals->openTMRec, kRetryTimer);
- SETMYA5(oldA5);
- return;
- }
-
- myGlobals->waitForBind = false;
-
- //
- // If the bind is complete, check if there was a bind error. If there was,
- // disconnect and tell AURP we did not connect successfully.
- //
- if(myGlobals->bindErr) {
- DOXTIDISCONNECT(myVarsPtr);
- SETMYA5(oldA5);
- CONNDONE( -1 );
- return;
- }
- }
-
- //
- // If the open has not been successfully completed, try it.
- //
- if(myGlobals->fd == -1) {
- if(do_open(myVarsPtr)) {
- PrimeTime((QElemPtr) myGlobals->openTMRec, kRetryTimer);
- SETMYA5(oldA5);
- return;
- }
- }
-
- //
- // The open has completed successfully, if the bind hasn't completed, try it.
- //
- if(!myGlobals->bindComplete) {
- if(do_bind(myVarsPtr)) {
- //
- // if the bind fails immediately, close the endpoint so we can try again
- //
- t_close(myGlobals->fd);
- myGlobals->fd = -1;
- }
- else {
- //
- // Because we are called by the time manager we have to leave the routine
- // to allow for the T_BINDCOMPLETE event to be called.
- //
- myGlobals->waitForBind = true;
- }
- PrimeTime((QElemPtr) myGlobals->openTMRec, kRetryTimer);
- SETMYA5(oldA5);
- return;
- }
-
- //
- // The bind and open are complete. If we are the calling router,
- // issue the connect.
- //
- if (myGlobals->theConfig.isCalling) {
- do_connect(myVarsPtr);
- }
-
-
- SETMYA5(oldA5);
- return;
- }
-
-
- /*____________________________________________________________________________
- try_reconnect (XTIShellVarsPtr myVarsPtr)
-
- If the user configuration specified automatic reconnection, install the
- Time Manager routine to reconnect. This code should not need any
- modifications.
-
- Returns: error code
-
- Parameters: myVarsPtr
- ______________________________________________________________________________*/
- static int
- try_reconnect( XTIShellVarsPtr myVarsPtr )
- {
- CShellGlobalsPtr myGlobals = myVarsPtr->cGlobals;
-
-
- if (myGlobals->theConfig.autoReconn) {
- myGlobals->isReconnecting = true;
- //
- // If we are the calling router, delay the connect momentarily
- // to give the answering side a chance to start listening
- //
- if (myGlobals->theConfig.isCalling) {
- PrimeTime((QElemPtr) myGlobals, kRetryTimer);
- }
- else {
- return(XTICONNECT(myVarsPtr));
- }
- }
- else {
- DOXTIDISCONNECT(myVarsPtr);
- return(-1);
- }
-
- return(0);
- }
-
-
- /*____________________________________________________________________________
- do_open (XTIShellVarsPtr myVarsPtr)
-
- This routine is called from the try_open routine. It attempts a t_open.
- The slot ID is used as the provider name. You may want to change this.
-
- Returns: error code
-
- Parameters: myVarsPtr
- ______________________________________________________________________________*/
- static int
- do_open( XTIShellVarsPtr myVarsPtr )
- {
- CShellGlobalsPtr myGlobals = myVarsPtr->cGlobals;
- struct t_info info;
- char providerName[2];
-
-
- //
- // Set up and call the t_open. This will be a non blocking endpoint.
- // Unless absolutely necessary, it should be left non blocking.
- //
- providerName[0] = 0;
- providerName[1] = myVarsPtr->OurSlotId;
- myGlobals->fd = t_open(providerName, O_NONBLOCK, &info );
- if (myGlobals->fd == -1) {
- return(-1);
- }
-
- //
- // Install the notifier completion routine.
- //
- if (t_install_notifier (myGlobals->fd, asyncReceive, myVarsPtr))
- return(-1);
-
- //
- // By setting bindComplete to false, we are assured the bind will be
- // attempted on returning to the try_open routine.
- //
- myGlobals->bindComplete = false;
-
-
- return(0);
- }
-
-
- /*____________________________________________________________________________
- do_bind (XTIShellVarsPtr myVarsPtr)
-
- This routine is called from the try_open routine after the t_open is
- complete. It attempts a t_bind. X.25 specific addressing is used and will
- need to changed.
-
- Returns: error code
-
- Parameters: myVarsPtr
- ______________________________________________________________________________*/
- static int
- do_bind( XTIShellVarsPtr myVarsPtr )
- {
- CShellGlobalsPtr myGlobals = myVarsPtr->cGlobals;
- struct t_bind bindRequest;
-
- bindRequest.addr.maxlen = sizeof(TTSAP);
- bindRequest.addr.len = sizeof(TTSAP);
- bindRequest.addr.buf = (char*) &myGlobals->theConfig.localAddr;
- bindRequest.qlen = myGlobals->theConfig.isCalling ? 0 : 1;
-
- if (t_bind( myGlobals->fd, &bindRequest, nil ))
- return(-1);
-
- return(0);
- }
-
-
- /*____________________________________________________________________________
- do_connect (XTIShellVarsPtr myVarsPtr)
-
- This routine is called from the try_open routine after the open and bind are
- complete. It is called only if we are the calling router. There is
- X.25 specific address information here which will need to be modified.
-
- Returns:
-
- Parameters: myVarsPtr
- ______________________________________________________________________________*/
- static void
- do_connect( XTIShellVarsPtr myVarsPtr )
- {
- CShellGlobalsPtr myGlobals = myVarsPtr->cGlobals;
- struct t_call sndcall;
- OSErr error = noErr;
-
- //
- // Set up the t_call structure. Put in the correct address
- // for your particular link type.
- //
- sndcall.addr.maxlen = sizeof(TTSAP);
- sndcall.addr.len = sizeof(TTSAP);
- sndcall.addr.buf = (char*) &myGlobals->theConfig.remoteAddr;
- sndcall.opt.maxlen = 0;
- sndcall.opt.len = 0;
- sndcall.udata.maxlen = 0;
- sndcall.udata.len = 0;
-
- //
- // Make the t_connect call. It will return -1 since we are asynchronous
- //
- t_connect( myGlobals->fd, &sndcall, nil ) ;
- //
- // Check the actual error
- //
- error = t_ERRNO( myGlobals->fd );
- if(error != TNODATA) {
- //
- // If a T_NODATA error occurred, we are stuck. Log the connection not
- // established message, disconnect, and tell AURP the connection failed.
- //
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnReqFailLogIx]);
- DOXTIDISCONNECT(myVarsPtr);
- CONNDONE( -1 );
- }
-
- }
-
-
- /*____________________________________________________________________________
- reconnect (void)
-
- The Time Manager reconnect routine. Installed by try_reconnect routine
- which is called whenever we think the connection has dropped and we
- want to attempt to reconnect. This code should not need any modifications.
-
- Returns:
-
- Parameters:
- ______________________________________________________________________________*/
- static void
- reconnect(void)
- {
- XTIShellVarsPtr myVarsPtr = GETGLOBALS();
- CShellGlobalsPtr myGlobals = myVarsPtr->cGlobals;
- long oldA5;
-
- oldA5 = GETMYA5();
- SETMYA5(myGlobals->myA5);
-
-
- if(XTICONNECT(myVarsPtr)) {
- CONNDONE( -1 );
- }
-
- SETMYA5(oldA5);
-
- }
-
-
- /*____________________________________________________________________________
- get_disconnect (XTIShellVarsPtr myVarsPtr)
-
- A disconnect event has been received on the endpoint, go get it. This
- code should not need any modifications.
-
- Returns: error code
-
- Parameters: myVarsPtr
- ______________________________________________________________________________*/
- static void
- get_disconnect( XTIShellVarsPtr myVarsPtr )
- {
- CShellGlobalsPtr myGlobals = myVarsPtr->cGlobals;
- struct t_discon myDisconnect;
-
-
- myDisconnect.udata.maxlen = 0;
- myDisconnect.udata.buf = nil;
- myDisconnect.udata.len = 0;
- myDisconnect.reason = 0;
- myDisconnect.sequence = 0;
-
- //
- // Receive the disconnect event. We don't care what the error
- // returned is because we are going to disconnect anyway.
- //
- t_rcvdis( myGlobals->fd, &myDisconnect );
-
- //
- // If we were connected, log the connection went down message, otherwise log
- // the connection request refused message.
- //
- if (myGlobals->isConnected)
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnDownLogIx]);
- else {
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnClearLogIx]);
- }
- myGlobals->isConnected = false;
-
- //
- // Complete the disconnect
- //
- DOXTIDISCONNECT(myVarsPtr);
- //
- // Attempt to reconnect
- //
- if (try_reconnect(myVarsPtr)) {
- CONNDONE( -1 );
- }
- }
-
- /*____________________________________________________________________________
- doSendErr (XTIShellVarsPtr myVarsPtr)
-
- This routine is called when a send error occurs. Assume the connection
- has gone down. This code should not need any modifications.
-
- Returns:
-
- Parameters: myVarsPtr
- ______________________________________________________________________________*/
- static void
- doSendErr ( XTIShellVarsPtr myVarsPtr )
- {
- CShellGlobalsPtr myGlobals = myVarsPtr->cGlobals;
-
- //
- // Log that the connection went down and complete disconnection
- //
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnDownLogIx]);
- DOXTIDISCONNECT(myVarsPtr);
- //
- // Attempt to reconnect
- //
- if(try_reconnect(myVarsPtr))
- CONNDONE( -1 );
-
- }
-
- /*____________________________________________________________________________
- doReadErr (XTIShellVarsPtr myVarsPtr)
-
- This routine is called when a read error occurs. Assume the connection
- went down. This code should not need any modifications.
-
- Returns:
-
- Parameters: myVarsPtr
- ______________________________________________________________________________*/
- static void
- doReadErr ( XTIShellVarsPtr myVarsPtr )
- {
- CShellGlobalsPtr myGlobals = myVarsPtr->cGlobals;
-
- //
- // Log that the connection went down and complete disconnection
- //
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnDownLogIx]);
- DOXTIDISCONNECT(myVarsPtr);
-
- //
- // Attempt to reconnect
- //
- if(try_reconnect(myVarsPtr))
- CONNDONE( -1 );
-
- }
-
-
-
- /*____________________________________________________________________________
- READDONE (XTIShellVarsPtr myVarsPtr)
-
- This routine is called from assembly when the read buffer is returned from
- AURP. It is only called if data is outstanding. This code should not need
- any modifications.
-
- Returns:
-
- Parameters: myVarsPtr
- ______________________________________________________________________________*/
- void
- READDONE( XTIShellVarsPtr myVarsPtr )
- {
- //
- // Decrement the number of packets waiting to be read and get the data
- //
- myVarsPtr->rcvPktsWaiting--;
- get_data( myVarsPtr );
- }
-
-
-
- /*____________________________________________________________________________
- get_data (XTIShellVarsPtr myVarsPtr)
-
- This routine is called to get data that is waiting to be read. This data
- is not necessarily a complete packet. It is called by READDONE and when a
- T_DATA event is received. This code should not need any modifications.
-
- Returns:
-
- Parameters: myVarsPtr
- ______________________________________________________________________________*/
- static void
- get_data( XTIShellVarsPtr myVarsPtr )
- {
- int bytesRead;
- int flags;
- Boolean gotEndOfBuffer = false;
- char *buf;
- OSErr error = noErr;
- int event;
- CShellGlobalsPtr myGlobals = myVarsPtr->cGlobals;
- long sr;
-
- buf = myGlobals->receiveBuffer;
- //
- // If we are in waitMoreData state, the receiveBuffer is "empty"
- //
- if (!myGlobals->waitMoreData) {
- myGlobals->rcvBuffLen = 0;
- myVarsPtr->rcvBufAvail = false; /* flag is cleared in the assembler routine */
- }
- else {
- myGlobals->waitMoreData = false;
- }
-
- //
- // Read until we get a complete packet or there is no more data to be read
- //
- while(!error && !gotEndOfBuffer) {
- flags = 0;
- bytesRead = t_rcv( myGlobals->fd, &(buf[myGlobals->rcvBuffLen]),
- myVarsPtr->maxRPktSz - myGlobals->rcvBuffLen, &flags );
- //
- // bytesRead equal to -1 indicates an error, find out what it is
- //
- if (bytesRead == -1) {
- error = t_ERRNO( myGlobals->fd );
- }
- else {
- myGlobals->rcvBuffLen += bytesRead;
- //
- // If we have received more than we asked for, we have serious problems,
- // so tear down the connection
- //
- if (myGlobals->rcvBuffLen > myVarsPtr->maxRPktSz) {
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnDownLogIx]);
- DOXTIDISCONNECT(myVarsPtr);
- CONNDONE( -1 );
- return;
- }
- //
- // If the T_MORE flag isn't set, the packet is complete
- //
- if (!(flags & T_MORE))
- gotEndOfBuffer = true;
- }
- }
-
- //
- // If we got the whole buffer, save the interrupt level and
- // give the buffer to AURP.
- //
- if (gotEndOfBuffer) {
- sr = GETSR ();
- (*myVarsPtr->AURPDispatch)(kAURPRead, myVarsPtr->AURPRefNum,
- myVarsPtr->otherNode, myGlobals->rcvBuffLen, buf);
- }
-
- //
- // If there was an error, check it and take appropriate action.
- //
- if (error) {
- switch (error)
- {
- case TNODATA:
- //
- // This is the case where we did not receive the complete packet
- // so we still have a partial buffer.
- //
- myGlobals->waitMoreData = true;
- break;
-
- case TLOOK:
- event = t_look ( myGlobals->fd ) ;
- if (event == T_DISCONNECT)
- {
- get_disconnect( myVarsPtr );
- }
- else doReadErr( myVarsPtr );
- return;
- default:
- doReadErr( myVarsPtr );
- return;
- }
- }
-
- return;
- }
-
- /*____________________________________________________________________________
- get_connect (XTIShellVarsPtr myVarsPtr)
-
- This routine is called when a T_CONNECT event is received. Go get the
- connect. This code should not need any modifications.
-
- Returns:
-
- Parameters: myVarsPtr
- ______________________________________________________________________________*/
- static void
- get_connect( XTIShellVarsPtr myVarsPtr )
- {
- CShellGlobalsPtr myGlobals = myVarsPtr->cGlobals;
-
-
- if (t_rcvconnect( myGlobals->fd, nil ))
- {
- //
- // If an error occurred on the receive connect, log
- // the connection not established message, disconnect,
- // and tell AURP the connection failed.
- //
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnReqFailLogIx]);
- DOXTIDISCONNECT(myVarsPtr);
- if(try_reconnect(myVarsPtr))
- CONNDONE( -1 );
- return;
- } else {
- myGlobals->isConnected = true;
-
- //
- // Log the connection established message and tell AURP
- // the connection was successful.
- //
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnectLogIx]);
- if(!myGlobals->toldConnDone) {
- CONNDONE( 0 );
- myGlobals->toldConnDone = false;
- }
-
- myGlobals->isReconnecting = false;
- }
- }
-
- /*____________________________________________________________________________
- get_listen (XTIShellVarsPtr myVarsPtr)
-
- This routine is called when a T_LISTEN event occurs. If password
- protection is desired, code should be added to verify it before
- accepting the connection.
-
- Returns: error code
-
- Parameters: myVarsPtr
- ______________________________________________________________________________*/
- static int
- get_listen( XTIShellVarsPtr myVarsPtr )
- {
- struct t_call call;
- CShellGlobalsPtr myGlobals = myVarsPtr->cGlobals;
-
-
- call.addr.buf = (char*) &myGlobals->theConfig.remoteAddr;
- call.addr.maxlen = sizeof(TTSAP);
- call.opt.buf = nil;
- call.udata.maxlen = 0;
- call.udata.buf = nil;
-
- //
- // Get the listen event. If we fail to get it, log connection down,
- // disconnect, and try to reconnect.
- //
- if (t_listen( myGlobals->fd, &call ))
- {
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnDownLogIx]);
- DOXTIDISCONNECT(myVarsPtr);
- return( try_reconnect(myVarsPtr) );
-
- }
-
- //
- // Accept the connection.
- //
- if ( t_accept(myGlobals->fd, myGlobals->fd, &call ) )
- {
- //
- // If an error occurs on the t_accept, log connection down, disconnect,
- // and try to reconnect.
- //
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnDownLogIx]);
- DOXTIDISCONNECT(myVarsPtr);
- return( try_reconnect(myVarsPtr) );
- }
-
- return(0);
-
- }
-
- /*____________________________________________________________________________
- check_send ( XTIShellVarsPtr myVarsPtr, int dataSent )
-
- This routine is called when a T_SENDCOMPLETE event occurs. Check
- the results and act accordingly. This code should not need any
- modifications.
-
- Returns:
-
- Parameters: myVarsPtr, dataSent
- ______________________________________________________________________________*/
-
- static void check_send( XTIShellVarsPtr myVarsPtr, int dataSent ) {
- CShellGlobalsPtr myGlobals;
- int event;
-
-
- myGlobals = myVarsPtr->cGlobals;
-
- //
- // If the dataSent is less than the buffer length, all the
- // data was not sent so send the rest of it.
- //
- if (dataSent < myGlobals->sendBuffLen)
- {
- myGlobals->sendBuffLen -= dataSent;
- myGlobals->dataToSendPtr += dataSent;
- if (t_snd( myGlobals->fd, myGlobals->dataToSendPtr, myGlobals->sendBuffLen, 0 )) {
- //
- // If the t_snd failed, find out why.
- //
- switch (t_ERRNO( myGlobals->fd ))
- {
- case TFLOW:
- myGlobals->isFlowControlled = true;
- break;
-
- case TLOOK:
- event = t_look ( myGlobals->fd ) ;
- if (event == T_DISCONNECT)
- {
- get_disconnect( myVarsPtr );
- }
- else doSendErr( myVarsPtr );
- break;
-
- default:
- doSendErr( myVarsPtr );
- break;
-
- }
- }
- }
- else
- {
- //
- // All the data was successfully sent. Tell AURP the write
- // is complete.
- //
- myGlobals->isSending = false;
- (*myVarsPtr->AURPDispatch)(kAURPWriteDone, myVarsPtr->AURPRefNum, myVarsPtr->wDSPtr, 0);
- }
-
- }
-
- /*____________________________________________________________________________
- AsyncReceive (int fd, int event, unsigned long providerInfo,
- int errno, void *cookie)
-
- This is the installed completion routine. All XTI events are processed
- here. The procedure for each event is basically the same - if there
- was an error, log a connection down error message, disconnect, and tell
- AURP. Otherwise, call a routine to handle the event. This routine should
- not need to be modified unless you want to perform different or
- additional error handling.
-
- Returns:
-
- Parameters: fd, event, providerInfo, errNo, -> cookie
- ______________________________________________________________________________*/
-
- static void asyncReceive (int fd, int event, unsigned long providerInfo,
- int errno, void *cookie)
- {
- #pragma unused (providerInfo)
- XTIShellVarsPtr myVarsPtr;
- CShellGlobalsPtr myGlobals;
-
-
-
- myVarsPtr = (XTIShellVarsPtr) cookie;
- myGlobals = myVarsPtr->cGlobals;
-
- switch (event)
- {
- case T_BINDCOMPLETE:
- //
- // An outstanding bind request has completed
- //
- myGlobals->bindComplete = true;
- myGlobals->bindErr = errno;
- if(errno) {
- break;
- }
- myGlobals->bindErr = t_rcvbind (fd, nil);
- if(myGlobals->bindErr) {
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnReqFailLogIx]);
- break;
- }
- break;
-
- case T_CONNECT:
- //
- // You are the calling router and a connect response
- // to your connect request has been received.
- //
- if (errno)
- {
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnDownLogIx]);
- DOXTIDISCONNECT(myVarsPtr);
- if(try_reconnect(myVarsPtr))
- CONNDONE( -1 );
- break;
- }
-
- get_connect( myVarsPtr );
-
- break;
-
- case T_DISCONNECT:
- //
- // A router is trying to disconnect
- //
- if (errno) {
- DOXTIDISCONNECT(myVarsPtr);
- if(try_reconnect(myVarsPtr))
- CONNDONE( -1 );
- break;
- }
-
- get_disconnect( myVarsPtr );
-
- break;
-
- case T_PASSCON:
- //
- // You are the answering router and the connection you accepted
- // is now complete.
- //
- if (errno)
- {
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnDownLogIx]);
- DOXTIDISCONNECT(myVarsPtr);
- if(try_reconnect(myVarsPtr))
- CONNDONE( -1 );
- break;
- }
-
- myGlobals->isConnected = true;
- // log connection established message
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnectLogIx]);
-
- if(!myGlobals->toldConnDone) {
- CONNDONE( 0 );
- myGlobals->toldConnDone = false;
- }
- myGlobals->isReconnecting = false;
-
- case T_GODATA:
- //
- // The connection was flow controlled, but now it is not.
- //
- if (errno == -1)
- {
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnDownLogIx]);
- DOXTIDISCONNECT(myVarsPtr);
- if(try_reconnect(myVarsPtr))
- CONNDONE( -1 );
- break;
- }
-
- //
- // T_GODATA is the same as T_SENDCOMPLETE, only 0 bytes are sent
- //
- myGlobals->isFlowControlled = false;
- errno = 0;
- //
- // continue with the code for T_SENDCOMPLETE
- //
-
- case T_SENDCOMPLETE:
- //
- // A outstanding send is complete
- //
- if (errno == -1)
- {
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnDownLogIx]);
- DOXTIDISCONNECT(myVarsPtr);
- if(try_reconnect(myVarsPtr))
- CONNDONE( -1 );
- break;
- }
-
- check_send(myVarsPtr, errno);
- break;
-
- case T_LISTEN:
- //
- // You are the answering router and a connect request
- // has been received.
- //
- if (errno)
- {
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnDownLogIx]);
- DOXTIDISCONNECT(myVarsPtr);
- if(try_reconnect(myVarsPtr))
- CONNDONE( -1 );
- break;
- }
-
- if(get_listen( myVarsPtr ))
- {
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnDownLogIx]);
- DOXTIDISCONNECT(myVarsPtr);
- if(try_reconnect(myVarsPtr))
- CONNDONE( -1 );
- break;
- }
-
- break;
-
- case T_DATA:
- //
- // Data has been received.
- //
- if (errno)
- {
- (*myVarsPtr->AURPDispatch)(kAURPLogMsg, myVarsPtr->AURPRefNum, 0, myGlobals->logStr[kConnDownLogIx]);
- DOXTIDISCONNECT(myVarsPtr);
- if(try_reconnect(myVarsPtr))
- CONNDONE( -1 );
- break;
- }
-
- if (myVarsPtr->rcvBufAvail || myGlobals->waitMoreData) {
- get_data( myVarsPtr );
- } else {
- myVarsPtr->rcvPktsWaiting++;
- }
- break;
-
- default:
- DOXTIDISCONNECT(myVarsPtr);
-
- if(try_reconnect(myVarsPtr))
- CONNDONE( -1 );
-
- break;
- }
-
- return;
- }
-
- /************************/
- /* Bin2Ascii */
- /************************/
- static void Bin2Ascii(unsigned char *bin, unsigned char len, unsigned char *ascii)
- {
- unsigned char cnt;
-
- for (cnt = 0; cnt < len; cnt++) {
- if (cnt & 0x01) {
- ascii[cnt] = bin[cnt >> 1] & 0x0F;
- } else {
- ascii[cnt] = bin[cnt >> 1] >> 4;
- }
-
-
-
- if (ascii[cnt] >= 0x0A && ascii[cnt] <= 0x0F) {
- ascii[cnt] += 'A';
- }
- else {
- ascii[cnt] += '0';
- }
-
- }
- return;
- }